﻿using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using CDA = System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.SqlClient;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Linq.Dynamic;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using System.Web;
using System.Web.DynamicData;
using SWD = System.Web.DynamicData;
using System.Web.UI.WebControls;
using Dimok;

namespace Data.LINQ {

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Table view. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class TableView<T> : IQueryable<T> where T : class {
		private IQueryable<T> baseQuery;
		public Table<T> Table;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Constructor. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="Table">	The table. </param>
		/// <param name="Query">	The query. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public TableView(Table<T> Table, IQueryable<T> Query) {
			this.Table = Table;
			this.baseQuery = Query;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data set. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	The data set. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataSet GetDataSet() { return GetDataSet(""); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data set. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="AddRecordIfEmpty">	true to add record if empty. </param>
		///
		/// <returns>	The data set. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataSet GetDataSet(bool AddRecordIfEmpty) { return GetDataSet("", AddRecordIfEmpty); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data set. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="TableName">	Name of the table. </param>
		///
		/// <returns>	The data set. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataSet GetDataSet(string TableName) { return GetDataSet(new DataSet(), TableName); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data set. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="TableName">				Name of the table. </param>
		/// <param name="AddRecordIfEmpty">	true to add record if empty. </param>
		///
		/// <returns>	The data set. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataSet GetDataSet(string TableName, bool AddRecordIfEmpty) {
			return GetDataSet(new DataSet(), TableName, AddRecordIfEmpty);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data set. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="DS">					The ds. </param>
		/// <param name="TableName">	Name of the table. </param>
		///
		/// <returns>	The data set. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataSet GetDataSet(DataSet DS, string TableName) { return GetDataSet(DS, TableName, false); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data set. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="DS">								The ds. </param>
		/// <param name="TableName">				Name of the table. </param>
		/// <param name="AddRecordIfEmpty">	true to add record if empty. </param>
		///
		/// <returns>	The data set. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataSet GetDataSet(DataSet DS, string TableName, bool AddRecordIfEmpty) {
			DS.Tables.Add(GetDataTable(TableName, AddRecordIfEmpty));
			return DS;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data table. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	The data table. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataTable GetDataTable() { return GetDataTable(""); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data table. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="AddRecordIfEmpty">	true to add record if empty. </param>
		///
		/// <returns>	The data table. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataTable GetDataTable(bool AddRecordIfEmpty) { return GetDataTable("", AddRecordIfEmpty); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data table. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="DataTableName">	Name of the data table. </param>
		///
		/// <returns>	The data table. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataTable GetDataTable(string DataTableName) { return GetDataTable(DataTableName, false); }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the data table. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="DataTableName">		Name of the data table. </param>
		/// <param name="AddRecordIfEmpty">	true to add record if empty. </param>
		///
		/// <returns>	The data table. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataTable GetDataTable(string DataTableName, bool AddRecordIfEmpty) {
			if (DataTableName + "" == "") DataTableName = Table.Context.Mapping.GetTable(typeof(T)).TableName;
			DataTable dt = new DataTable(DataTableName);
			new SqlDataAdapter(Table.Context.GetCommand(baseQuery) as SqlCommand).Fill(dt);
			if (dt.Rows.Count == 0 && AddRecordIfEmpty)
				dt.Rows.Add();
			return dt;
		}
		// public static implicit operator IQueryable<T>(TableView<T> t) { return t.baseQuery; } 

		#region IEnumerable<T> Members
		public IEnumerator<T> GetEnumerator() { return baseQuery.GetEnumerator(); }
		#endregion

		#region IEnumerable Members

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the enumerator. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <returns>	The enumerator. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
		#endregion

		#region IQueryable Members

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Gets the type of the element(s) that are returned when the expression tree associated with this
		/// instance of <see cref="T:System.Linq.IQueryable" /> is executed. 
		/// </summary>
		///
		/// <value>	The type of the element. </value>
		///
		/// ### <returns>	
		/// A <see cref="T:System.Type" /> that represents the type of the element(s) that are returned
		/// when the expression tree associated with this object is executed. 
		/// </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public Type ElementType { get { return baseQuery.ElementType; } }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	
		/// Gets the expression tree that is associated with the instance of <see cref="T:
		/// System.Linq.IQueryable" />. 
		/// </summary>
		///
		/// <value>	The expression. </value>
		///
		/// ### <returns>	
		/// The <see cref="T:System.Linq.Expressions.Expression" /> that is associated with this instance
		/// of <see cref="T:System.Linq.IQueryable" />. 
		/// </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public Expression Expression { get { return baseQuery.Expression; } }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the query provider that is associated with this data source. </summary>
		///
		/// <value>	The provider. </value>
		///
		/// ### <returns>	
		/// The <see cref="T:System.Linq.IQueryProvider" /> that is associated with this data source. 
		/// </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public IQueryProvider Provider { get { return baseQuery.Provider; } }
		#endregion
	}
}